package gcode

import (
	"gorm.io/gorm"
)

// GcodeRepo 数据库代码生成相关的仓库接口
type GcodeRepo interface {
	// 获取当前数据库名
	GetCurrentDatabaseName() (string, error)
	// 获取所有数据库名
	GetAllDatabases() ([]string, error)
	// 获取数据库下的所有表
	GetDatabaseTables(dbName string) ([]string, error)
	// 获取表结构详情
	GetTableStructure(database, table string) (*TableStructure, error)
	// 获取表的列信息
	GetTableColumns(database, table string) ([]ColumnInfo, error)
	// 获取表的主键
	GetTablePrimaryKeys(database, table string) ([]string, error)
	// 获取表的索引
	GetTableIndexes(database, table string) ([]IndexInfo, error)
}

// GcodeRepoImpl 数据库代码生成仓库实现
type GcodeRepoImpl struct {
	db *gorm.DB
}

// NewGcodeRepo 创建新的GcodeRepo实例
func NewGcodeRepo(db *gorm.DB) GcodeRepo {
	return &GcodeRepoImpl{db: db}
}

// GetCurrentDatabaseName 获取当前数据库名
func (r *GcodeRepoImpl) GetCurrentDatabaseName() (string, error) {
	var currentDB string
	err := r.db.Raw("SELECT DATABASE()").Scan(&currentDB).Error
	return currentDB, err
}

// GetAllDatabases 获取所有数据库名
func (r *GcodeRepoImpl) GetAllDatabases() ([]string, error) {
	var databases []string
	err := r.db.Raw("SHOW DATABASES").Scan(&databases).Error
	return databases, err
}

// GetDatabaseTables 获取数据库下的所有表
func (r *GcodeRepoImpl) GetDatabaseTables(dbName string) ([]string, error) {
	var tables []string
	err := r.db.Raw("SHOW TABLES FROM `" + dbName + "`").Scan(&tables).Error
	return tables, err
}

// GetTableStructure 获取表结构详情
func (r *GcodeRepoImpl) GetTableStructure(database, table string) (*TableStructure, error) {
	var tableInfo TableStructure
	err := r.db.Raw(`
		SELECT 
			TABLE_NAME as name,
			ENGINE as engine,
			TABLE_COMMENT as comment,
			CREATE_TIME as create_time,
			UPDATE_TIME as update_time
		FROM 
			information_schema.TABLES
		WHERE 
			TABLE_SCHEMA = ? AND TABLE_NAME = ?
	`, database, table).Scan(&tableInfo).Error

	if err != nil {
		return nil, err
	}

	// 获取列信息
	columns, err := r.GetTableColumns(database, table)
	if err != nil {
		return nil, err
	}
	tableInfo.Columns = columns

	// 获取主键信息
	primaryKeys, err := r.GetTablePrimaryKeys(database, table)
	if err != nil {
		return nil, err
	}
	tableInfo.PrimaryKeys = primaryKeys

	// 获取索引信息
	indexes, err := r.GetTableIndexes(database, table)
	if err != nil {
		return nil, err
	}
	tableInfo.Indexes = indexes

	return &tableInfo, nil
}

// GetTableColumns 获取表的列信息
func (r *GcodeRepoImpl) GetTableColumns(database, table string) ([]ColumnInfo, error) {
	var columns []ColumnInfo
	err := r.db.Raw(`
		SELECT 
			COLUMN_NAME as name,
			COLUMN_TYPE as type,
			COLUMN_KEY as column_key,
			IS_NULLABLE as is_nullable,
			COLUMN_DEFAULT as default_value,
			EXTRA as column_extra,
			COLUMN_COMMENT as comment
		FROM 
			information_schema.COLUMNS 
		WHERE 
			TABLE_SCHEMA = ? AND TABLE_NAME = ?
		ORDER BY 
			ORDINAL_POSITION
	`, database, table).Scan(&columns).Error
	return columns, err
}

// GetTablePrimaryKeys 获取表的主键
func (r *GcodeRepoImpl) GetTablePrimaryKeys(database, table string) ([]string, error) {
	var primaryKeys []string
	err := r.db.Raw(`
		SELECT 
			COLUMN_NAME
		FROM 
			information_schema.KEY_COLUMN_USAGE
		WHERE 
			TABLE_SCHEMA = ? AND TABLE_NAME = ? AND CONSTRAINT_NAME = 'PRIMARY'
		ORDER BY 
			ORDINAL_POSITION
	`, database, table).Scan(&primaryKeys).Error
	return primaryKeys, err
}

// GetTableIndexes 获取表的索引
func (r *GcodeRepoImpl) GetTableIndexes(database, table string) ([]IndexInfo, error) {
	var indexes []IndexInfo
	err := r.db.Raw(`
		SELECT 
			INDEX_NAME as name,
			NON_UNIQUE as non_unique,
			GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) as columns
		FROM 
			information_schema.STATISTICS
		WHERE 
			TABLE_SCHEMA = ? AND TABLE_NAME = ?
		GROUP BY 
			INDEX_NAME, NON_UNIQUE
	`, database, table).Scan(&indexes).Error
	return indexes, err
}
